;

(function($) {

    var html = {
        fieldset: {
           tmpl: "<fieldset rel=\"content_block\" id=\"{{ $0 }}\"><legend>{{ $1 }}</legend>{{ $2 }}</fieldset>",
           vars: 3
        },

        dl: {
           tmpl: "<dl>{{ $0 }}</dl>",
           vars: 1
        },

        dt: {
           tmpl: "<dt>{{ $0 }}</dt>",
           vars: 2
        },

        dd: {
           tmpl: "<dd>{{ $0 }}{{ $1 }}</dd>",
           vars: 2
        },

        label: {
           tmpl: "<label class=\"optional\" for=\"{{ $1 }}\">{{ $0 }}</label>",
           vars: 2
        },

        input: {
           tmpl: "<input type=\"{{ $0 }}\" name=\"{{ $1 }}\" value=\"{{ $2 }}\" rel=\"{{ $3 }}\" id=\"{{ $4 }}\" class=\"{{ $5 }}\" />",
           vars: 6
        },

        textarea: {
           tmpl: "<textarea name=\"{{ $0 }}\" rel=\"{{ $2 }}\" cols=\"80\" rows=\"25\" class=\"{{ $3 }}\">{{ $1 }}</textarea>",
           vars: 4
        },

        add_icon: {
           tmpl: "<span class=\"ui-icon ui-icon-plus\"/>",
           vars: 0
        },

        del_icon: {
           tmpl: "<span class=\"ui-icon ui-icon-close\"/>",
           vars: 0
        },

        add_button: {
           tmpl: "<a class=\"link_button ui-state-default ui-corner-all\" href=\"#\" rel=\"multiple\">{{ $0 }}</a>",
           vars: 1
        },

        del_button: {
           tmpl: "<a class=\"link_button ui-state-default ui-corner-all\" href=\"#\" rel=\"delete\">{{ $0 }}</a>",
           vars: 1
        },

        button: {
           tmpl: "<button type=\"{{ $0 }}\" class=\"{{ $2 }}\">{{ $1 }}</button>",
           vars: 3
        },

        buttons_group: {
            tmpl: "<div class=\"{{ $1 }}\">{{ $0 }}</div>",
            vars: 2
        }
    }

    var curIndex = {}, fieldsetIndex, indexSepr = '_n';

    $.extend({
       formConstructor: function(opt) {
           var $f = this;

           this.items = {};
           this.dialogOpt = {
               width:"226px"
           };
           this.formId = null;
           this.fieldsetIndex = 0;
           this.fileTypes = ['image', 'file'];

           if (opt) {
               $.extend(this, opt);
           }

           this._fieldsCount = function(dd, relId) {
               if (undefined === this.items[relId]) {
                   if (relId) {
                       var cnt = $(dd).parent().find("input[rel=" + relId + "],textarea[rel=" + relId + "]").length;
                       this.items[relId] = cnt;
                   } else {
                       this.items[relId] = 0;
                   }
               }
               return this.items[relId];
           }

           this.html = function(el, st, maxSt) {
               var h = html[el]["tmpl"];
               var st = st || [];
               if (h) {

                   if (html[el]["vars"] > st.length) {
                       var ln = st.length;
                       for (var j = ln; j < html[el]["vars"]; j++) {
                           st.push("");
                       }
                   }

                   for (var i = 0; i < st.length; i++) {
                       if (typeof st[i] == 'object') {
                           st[i] = st[i].join("");
                       }
                       h = (h.replace(new RegExp("{{[\\s]\\$" + i + "[\\s]}}"), st[i]));
                   }

               }
               return h;
           }

           this.cloneField = function(obj) {
               var name, type, rel;
               var dd = $(obj).parents("dd").get(0);
               var dt = $(dd).prev("dt").get(0);
               var element = $("input,textarea", dd).last().get(0);
               var newElement = null;

               if (element) {
                   name = this.getArrayName(element.name);
                   type = element.nodeName.toLowerCase() == 'input' ? element.type : 'textarea';
                   rel = element.getAttribute("rel");

                   var buttons = [
                       this.html("add_button", [
                           this.html("add_icon")
                       ]),

                       this.html("del_button", [
                           this.html("del_icon")
                       ])
                   ];

                   if (type != 'textarea') {
                       newElement = this.html("input", [type, name, '', rel]);
                   } else {
                       newElement = this.html("textarea", [name, '', rel, element.getAttribute('cols'), element.getAttribute('rows'), element.className]);
                   }

                   var newdt = this.html("dt", ["&nbsp;"]);
                   var newdd = this.html("dd", [newElement, buttons]);

                   var html = newdt + newdd;

                   this._fieldsCount(dd, rel);
                   $(html).insertAfter($(dd));

                   this.items[rel]++;
               }
           }

           this.removeField = function(obj) {
               var dd = $(obj).parents("dd");
               var element = $("input,textarea", dd).last().get(0);
               var rel = element.getAttribute("rel");

               this._fieldsCount(dd, rel);

               if (this.items[rel] <= 1) {
                   if (element.nodeName.toLowerCase() != 'textarea' && element.type == 'file') {
                       this.cloneField(obj);
                   } else {
                       this.setValue(element, "");
                       return;
                   }
               }

               var dt = dd.prev("dt");

               dd.remove();
               dt.remove();

               this.items[rel]--;
           }

           this.createField = function(opt, container) {
               var name = opt.name;
               var rel = opt.name;
               var id = opt.name;
               var value = opt.value || "";
               var type = opt.type || "text";
               var title = opt.label || "&nbsp;";
               var element, label, dt, dd, className = '';

               if ($.inArray(type, this.fileTypes) != -1) {
                   type = 'file';
               }

               if (undefined !== opt.attrs.class) {
                   className = opt.attrs.class;
               }

               if (undefined !== opt.fieldset && undefined !== opt.index) {
                   if (type == 'file') {
                       name = this.getFieldId(opt.fieldset, [opt.index], "_") + "[" + id + "]";
                   } else {
                       name = this.getFieldName(name, [opt.fieldset, opt.index]);
                   }
                   id = this.getFieldId(opt.fieldset, [opt.index, id]);
               }

               if (opt.type != 'textarea') {
                   element = this.html("input", [type, name, value, rel, id, className]);
               } else {
                   element = this.html("textarea", [name, value, rel, className]);
               }

               label = this.html("label", [title, name]);
               dt = this.html("dt", [label]);
               dd = this.html("dd", [element], 2);

               if (container) {
                   if (typeof container == "string") {
                       container = $(container);
                   }
                   $(dt + dd).appendTo(container);
               } else {
                   return dt + dd;
               }
           }

           this.createButton = function(opt, container) {

               var bt = this.html("button", [opt.type, opt.label, opt.class]);

               if (container) {
                   if (typeof container == "string") {
                       container = $(container);
                   }
                   $(bt).appendTo(container);
               } else {
                   return bt;
               }
           }

           this.createButtonsGroup = function(opt, buttons, container) {

               var el = [];

               $.each(buttons, function(i, bt) {
                   el.push( $f.createButton(bt) );
               });

               var sep = opt.separator || "";
               var group = this.html("buttons_group", [el.join(sep), opt.class]);

               if (container) {
                   if (typeof container == "string") {
                       container = $(container);
                   }
                   $(group).insertAfter(container);
               } else {
                   return group;
               }
           }

           this.createFieldset = function(block, container, opt) {

               var el = [];
               var index = this.getFieldsetIndex();
               opt.prependHtml = opt.prependHtml || "";
               opt.appendHtml = opt.appendHtml || "";
               opt.order = opt.order || 0;

               $.each(block.items, function(i, opt) {
                   opt.index = index;
                   opt.fieldset = block.name;
                   el[i] = ( $f.createField(opt) );
               });

               var orderName = this.getFieldName(index, ["order", block.name]);
               var orderId = this.getFieldId("order", [block.name, index]);
               var orderElement = this.html("input", ["hidden", orderName, opt.order, block.name, orderId]);

               var dl = this.html("dl", [el.join("")]);

               var fieldsetId = this.getFieldId(block.name, [index]);
               var fieldset = this.html("fieldset", [fieldsetId, block.legend, opt.prependHtml + dl + orderElement + opt.appendHtml]);

               this.incrFieldsetIndex();

               if (container) {
                   if (typeof container == "string") {
                       container = $(container);
                   }
                   $(fieldset).insertAfter(container);
               } else {
                   return fieldset;
               }
           }

           this.decrFieldsetIndex = function() {
               if (undefined === fieldsetIndex) {
                   fieldsetIndex = parseInt(this.fieldsetIndex);
               }
               if (fieldsetIndex > 0) {
                   fieldsetIndex--;
               }
           }

           this.incrFieldsetIndex = function() {
               if (undefined === fieldsetIndex) {
                   fieldsetIndex = parseInt(this.fieldsetIndex);
               }
               fieldsetIndex++;
           }

           this.getFieldsetIndex = function() {
               if (undefined === fieldsetIndex) {
                   fieldsetIndex = parseInt(this.fieldsetIndex);
               }
               return fieldsetIndex;
           }

           this.setValue = function(element, value) {
               if (element.nodeName != 'textarea') {
                   element.value = value;
               } else {
                   $(element).text(value);
               }
           }

           this.getElementNameParts = function(name) {
               var parts = name.split(/[\[\]]+|$/);
               if (name.indexOf("[]") == name.length - 2) {
                   parts.push("0");
               }
               return parts;
           }

           this.getFieldName = function(name, parts) {
               if (undefined !== parts) {
                   var res = [parts.shift()];
                   for (var i = 0; i < parts.length; i++) {
                       res.push("[" + parts[i] + "]");
                   }
                   res.push("[" + name + "]");
                   return res.join("");
               }
               return name;
           }

           this.getFieldId = function(name, parts, sep) {
               if (undefined !== parts) {
                   parts.unshift(name);
                   sep = sep||"-";
                   return parts.join(sep);
               }
               return name;
           }

           this.getArrayName = function(name) {
               var res = "";
               name = this.getElementNameParts(name);

               try {
                   if (name.length > 1) {
                       var a = name.pop().split(/[\-\_]/);
                       var firstIndex = 0, lastIndex = 0;

                       if (a.length > 1) {
                           lastIndex = parseInt(a.pop());
                       }

                       firstIndex = a.pop().replace(/[^\d]+/, "");

                       if (isNaN(firstIndex) || firstIndex <= 0) {
                           firstIndex = 0;
                       } else {
                           firstIndex = parseInt(firstIndex);
                       }

                       if (curIndex[firstIndex] !== undefined) {
                           lastIndex = ++curIndex[firstIndex];
                       } else {
                           curIndex[firstIndex] = ++lastIndex;
                       }

                       name.push(new String(firstIndex) + indexSepr + new String(lastIndex));
                   } else {
                       name.push(0);
                   }
               } catch (e) {
                   return res;
               }

               for (var i = 0; i < name.length; i++) {
                   if (i == 0) {
                       res += name[i];
                   } else {
                       res += ("[" + name[i] + "]");
                   }
               }
               return res;
           }

           this.error = function(obj) {
               info_dialog("Внимание", "Ошибка при редактировании объекта", null, this.dialogOpt);
           }
       }
    });

})(jQuery);

